package com.nuoniu.sibanyun.utils;

import com.nuoniu.sibanyun.common.lang.DateUtils;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.config.YmlConfig;

import com.nuoniu.sibanyun.utils.entity.UploadFileResult;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.multipart.MultipartFile;


import javax.servlet.ServletInputStream;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 类说明: 文件处理工具
 * @author 小啊刚 2020-06-27
 */
@Log4j2
public class FileUtils {

	/**
	 * 方法说明：单/多上传文件
	 * @param isRename 1: 需要重命名 2：不需要
	 * @param classDir 分类文件目录
	 * @author 小啊刚 2018-10-16 16:53
	 */
	public static List<String> uploadFile(MultipartFile[] files, int isRename,String classDir){
		if(StringUtils.isBlank(classDir))classDir="";
		List<String> fileNameList = new ArrayList<>();
		for (int i=0; i<files.length; i++) {
			String fileName = files[i].getOriginalFilename();  //文件名字
			String fileExtName = getFileExtName(fileName);
			if(StringUtils.isNotEmpty(fileExtName)) {
				String date = DateUtils.formatDate(new Date(),"yyyyMMdd/");
				String saveDir = YmlConfig.UPLOAD_FILE_PATH + classDir + date;
				String saveFileName;
				if(isRename == 1) {
					String fileNo = UUID.randomUUID().toString();
					saveFileName = fileNo + "." + fileExtName;
				}else {
					saveFileName = fileName;
				}
				String finalPath = saveDir + saveFileName;
				File targetFile = new File(saveDir);
				if(!targetFile.exists()){
					targetFile.mkdirs();
				}
				try {
					// 拿到输出流，同时重命名上传的文件
					FileOutputStream os = new FileOutputStream(finalPath);
					// 拿到上传文件的输入流
					FileInputStream in = (FileInputStream) files[i].getInputStream();
					// 以写字节的方式写文件
					byte[] buffer = new byte[10240];
					int size = 0;
					while((size = in.read(buffer))!= -1){
						os.write(buffer,0, size);
					}
					os.flush();
					os.close();
					in.close();
					fileNameList.add(classDir + date + saveFileName);
				}catch (Exception e){
					e.printStackTrace();
				}
			}
		}
		return fileNameList;
	}

	/**
	 * 单/多上传文件(返回原始文件名 和 存储相对路径)
	 * @param files
	 * @param classDir
	 * @return
	 */
	public static List<UploadFileResult> uploadFileResult(MultipartFile[] files, String classDir){
		List<UploadFileResult> resultList = new ArrayList<>();
		if(StringUtils.isBlank(classDir))classDir="";
		for (int i=0; i<files.length; i++) {
			String fileName = files[i].getOriginalFilename();  //文件名字
			String fileExtName = getFileExtName(fileName);
			if(StringUtils.isNotEmpty(fileExtName)) {
				UploadFileResult uploadFileResult = new UploadFileResult();
//				String date = DateUtils.formatDate(new Date(),"yyyyMMdd/");
				String saveDir = YmlConfig.UPLOAD_FILE_PATH + classDir ;
				File targetFile = new File(saveDir);
				//是否存在 文件
				if(!targetFile.exists()){
					targetFile.mkdirs();
				}
				String orgFileName = fileName;
				uploadFileResult.setFileName(fileName);
				getFileName(saveDir,orgFileName,uploadFileResult,0);
				fileName = uploadFileResult.getFileName();
				String finalPath = saveDir + fileName;
				try {
					// 拿到输出流，同时重命名上传的文件
					FileOutputStream os = new FileOutputStream(finalPath);
					// 拿到上传文件的输入流
					FileInputStream in = (FileInputStream) files[i].getInputStream();
					// 以写字节的方式写文件
					byte[] buffer = new byte[10240];
					int size = 0;
					while((size = in.read(buffer))!= -1){
						os.write(buffer,0, size);
					}
					os.flush();
					os.close();
					in.close();
					uploadFileResult.setFilePath(classDir + fileName);
				}catch (Exception e){
					e.printStackTrace();
				}
				resultList.add(uploadFileResult);
			}
		}
		return resultList;
	}


	private static void getFileName(String classDir,String orgFileName,UploadFileResult uploadFileResult,Integer repeatTimes){

		if(StringUtils.isBlank(classDir) || StringUtils.isBlank(orgFileName) || StringUtils.isBlank(uploadFileResult.getFileName())){
			return;
		}
		String finalPath = classDir + uploadFileResult.getFileName();
		File targetFile = new File(finalPath);
		if(targetFile.exists()){
			repeatTimes ++;
			String[] split = StringUtils.split(orgFileName, ".");
			if(split.length < 2)return;
			uploadFileResult.setFileName(split[0] + "(" + repeatTimes + ")." + split[1]);
			getFileName(classDir,orgFileName,uploadFileResult,repeatTimes);
		}
	}
	/**
	 * 富文本上传文件
	 */
	public static String upload(MultipartFile file){
		String date = DateUtils.formatDate(new Date(),"yyyyMMdd/");
		String saveDir = YmlConfig.UPLOAD_FILE_PATH + date;
		String fileName = file.getOriginalFilename();  //文件名字
		String fileExtName = getFileExtName(fileName);

		if(StringUtils.isNotEmpty(fileExtName)) {
			String saveFileName;
			String fileNo = UUID.randomUUID().toString();
			saveFileName = fileNo + "." + fileExtName;
			String finalPath = saveDir + saveFileName;
			File targetFile = new File(saveDir);
			if(!targetFile.exists()){
				targetFile.mkdirs();
			}
			try {
				// 拿到输出流，同时重命名上传的文件
				FileOutputStream os = new FileOutputStream(finalPath);
				// 拿到上传文件的输入流
				FileInputStream in = (FileInputStream) file.getInputStream();
				// 以写字节的方式写文件
				byte[] buffer = new byte[10240];
				int size = 0;
				while((size = in.read(buffer))!= -1){
					os.write(buffer,0, size);
				}
				os.flush();
				os.close();
				in.close();
				return  date + saveFileName;
			}catch (Exception e){
				e.printStackTrace();
			}
		}
		return "";
	}

	public static String upload(InputStream in, int isRename, String classDir, String fileName){
		if(StringUtils.isBlank(classDir))classDir="";
		String date = DateUtils.formatDate(new Date(),"yyyyMMdd/");
		String saveDir = YmlConfig.UPLOAD_FILE_PATH + classDir + date;
		String fileExtName = getFileExtName(fileName);

		if(StringUtils.isNotEmpty(fileExtName)) {
			String saveFileName;
			if(isRename == 1) {
				String fileNo = UUID.randomUUID().toString();
				saveFileName = fileNo + "." + fileExtName;
			}else {
				saveFileName = fileName;
			}
			String finalPath = saveDir + saveFileName;
			File targetFile = new File(saveDir);
			if (!targetFile.exists()) {
				targetFile.mkdirs();
			}
			FileOutputStream os = null;
			try {
				// 拿到输出流，同时重命名上传的文件
				os = new FileOutputStream(finalPath);
				// 以写字节的方式写文件
				byte[] buffer = new byte[10240];
				int size = 0;
				while ((size = in.read(buffer)) != -1) {
					os.write(buffer, 0, size);
				}
//				os.flush();
//				os.close();
//				in.close();
				return classDir + date + saveFileName;
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				try {
					os.flush();
					os.close();
				}catch (IOException e){
					log.error("上传文件，关闭输出流OS异常：{}",e.getMessage());
				}
			}
			if (null != in){
				try {
					in.close();
				} catch (IOException e) {
					log.error("上传文件，关闭输入流IN异常：{}",e.getMessage());
				}
			}
		}
		return null;
	}
	/**
	 * 方法说明: 删除文件或者目录下所有类容.
	 * @author Brando 2017-10-16 下午2:40:06
	 * @param file
	 */
	public static void deleteFile(File file) {
		if (file.exists()) {//判断文件是否存在
			if (file.isFile()) {//判断是否是文件
				file.delete();//删除文件
			} else if (file.isDirectory()) {//否则如果它是一个目录
				File[] files = file.listFiles();//声明目录下所有的文件 files[];
				for (int i = 0;i < files.length;i ++) {//遍历目录下所有的文件
					deleteFile(files[i]);//把每个文件用这个方法进行迭代
				}
				file.delete();//删除文件夹
			}
		} else {
			System.out.println("删除的文件不存在");
		}
	}

	/**
	 * 方法说明: 删除文件或者目录下所有类容.
	 * @author Brando 2017-10-16 下午2:44:47
	 * @param filePath
	 */
	public static void deleteFile(String filePath) {
		File file = new File(filePath);
		deleteFile(file);
	}

	/**
	 * 方法说明: 加载文件到StringBuffer里面.
	 * @author Brando 2017-12-22 下午2:11:39
	 * @param filePath
	 * @return
	 */
	public static StringBuffer loadFileToStringBuffer(String filePath) {
		StringBuffer buf = new StringBuffer();
		File file = new File(filePath);
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            while ((tempString = reader.readLine()) != null) {
            	buf.append(tempString);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
		return buf;
	}

	/**
	 * 方法说明: 创建文件目录.
	 * @author Brando 2015-2-3 下午01:26:56
	 * @param filePath String 文件路径.
	 */
	public static void makeDir(String filePath) {
		try {
			File file = new File(filePath);
			file.mkdirs();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 方法说明: 保存文件
	 * @author Brando 2015-2-15 上午11:09:41
	 * @param filePath 保存文件路径.
	 * @param content 保存文件类容.
	 */
	public static String saveFile(String filePath, String fileName, String content) {
		makeDir(filePath);
		appendContent(filePath + "/" + fileName, content);
		return filePath + "/" + fileName;
	}

	/**
	 * 方法说明: 追加文本文件.
	 * @author Brando 2015-2-3 下午04:49:17
	 * @param filePath String 保存文件路径.
	 * @param content String 保存正文.
	 */
	public static void appendContent(String filePath, String content) {
	    try {
	    	OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(filePath), "UTF-8");
	    	out.write(content);
	    	out.flush();
	        out.close();
	    } catch (IOException e) {
	        e.printStackTrace();
	    }
	}

	/**
	 * 方法说明: 获取文件扩展名
	 * @author Brando 2016-2-18 上午11:29:10
	 * @param fileName 文件名称.
	 * @return Stirng 文件扩展名, 如:png
	 */
	public static String getFileExtName(String fileName) {
		String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
		return fileExt;
	}

	/**
	 * 方法说明:
	 * @author 小啊刚 2018/9/7 10:22
	 * @param filePath 完整目录的文件地址. 如: C:/temp/temp.png
	 * @return String 文件名称.	如: temp.png
	 */
	public static String getFileNameFromPath(String filePath) {
		String fileName = filePath;
		int index = filePath.lastIndexOf("/");
		if(index == -1) {
			index = filePath.lastIndexOf("\\");
		}
		if(index != -1) {
			fileName = filePath.substring(index + 1);
		}
		return fileName;
	}

	/**
	 * 方法说明:拷贝文件目录.
	 * @author 小啊刚 2018/9/13 18:28
	 */
	public static void copyDirectiory(String sourceDir, String targetDir) throws IOException {
		//新建目标目录
		(new File(targetDir)).mkdirs();
		//获取源文件夹当下的文件或目录
		File[] file = (new File(sourceDir)).listFiles();
		for (int i = 0; i < file.length; i++) {
			if (file[i].isFile()) {
				//源文件
				File sourceFile = file[i];
				//目标文件
				File targetFile = new File(new File(targetDir).getAbsolutePath() + File.separator + file[i].getName());
				copyFile(sourceFile, targetFile);
			}
			if (file[i].isDirectory()) {
				//准备复制的源文件夹
				String dir1 = sourceDir + file[i].getName();
				//准备复制的目标文件夹
				String dir2 = targetDir + File.separator + file[i].getName();
				copyDirectiory(dir1, dir2);
			}
		}

	}

	/**
	 * 方法说明:拷贝文件
	 * @author 小啊刚 2018/9/13 18:28
	 */
	public static void copyFile(File sourcefile, File targetFile) throws IOException {

		//新建文件输入流并对它进行缓冲
		FileInputStream input = new FileInputStream(sourcefile);
		BufferedInputStream inbuff = new BufferedInputStream(input);

		//新建文件输出流并对它进行缓冲
		FileOutputStream out = new FileOutputStream(targetFile);
		BufferedOutputStream outbuff = new BufferedOutputStream(out);

		//缓冲数组
		byte[] b = new byte[1024 * 5];
		int len = 0;
		while ((len = inbuff.read(b)) != -1) {
			outbuff.write(b, 0, len);
		}

		//刷新此缓冲的输出流
		outbuff.flush();

		//关闭流
		inbuff.close();
		outbuff.close();
		out.close();
		input.close();
	}

	/**
	 * 方法说明：json文件解析
	 * @author 小啊刚 2019-02-27 14:23
	 */
	public static String readerJsonFile(String filePath) {
		File file = new File(filePath);
		BufferedReader reader = null;
		String jsonStr = "";
		try {
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			int line = 1;
			// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				// 显示行号
				jsonStr += tempString;
				line++;
			}
			System.out.println(jsonStr);
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
				}
			}
		}
		return jsonStr;
	}

	public static void main(String[] args) {

	}

}
